using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Thinksquirrel.Utilities;
using System;

[System.Serializable]
public struct WaveData
{
	public int maxEnemy;
	public MemberModel [] memModel;
}

public struct WaveNPCData
{
	public int npcID;
	public int prob;
}

public enum EBattleStatus
{
	NextTurn,
	NextWave,
	EndBattle,
}

//몇 턴에 필살기, 친구스킬 사용했는지 저장//
public struct TurnSeq
{
	public int turn;
	public int type;// 1:필살기  2:친구스킬//
	public TurnSeq(int _turn, int _type)
	{
		turn = _turn;
		type = _type;
	}
}

public partial class BattleManager : MonoBehaviour {

	private static BattleManager instance;
	
	public static BattleManager Instance{
		get{
			return instance;
		}
	}	

	void Awake()
	{
		instance = this;
		cam = gameObject.AddComponent<BattleCamera>();
		statusCheck = gameObject.AddComponent<BattleStatusCheck>();

		if(UserData.Instance.userModel==null) {
			bTestStartBattle = true;
			SoundController.Create();
			ResourceManager.Inst.PatchDataFile( ()=> {
				GameData.Init();
				CashData.Init();
				//TextData.Init();
				EventData.Init();
			});

			ShowTestBattleStartBtn(true);
		}
		GameObject battleSceneGo = new GameObject();
		battleSceneGo.name="BattleScene";
		BattleScene battleScene = battleSceneGo.AddComponent<BattleScene>();
		battleScene.isAbleTouch=false;
		if(bPlayBGM)
			battleScene.PlayBGM();
		//GameObject reporterGo = Instantiate( Resources.Load ("Prefab/Battle/Reporter") as GameObject) as GameObject;
		if(uiRootTrans==null)
			uiRootTrans = GameObject.Find("UI Root").transform;
	}

	public bool bPlayBGM=true;
	public string battleTestId="kth16";
	List<MemberModel> membersIntoBattle = new List<MemberModel>();
	List<MemberModel> pvpMembersIntoBattle = new List<MemberModel>();
	public bool isBossBattle;
	public int randomSeedTest = 100;
	public List<WaveData> waveDataList = new List<WaveData>();
	public List<BattlePawn> playerList = new List<BattlePawn>();
	public List<BattlePawn> targetablePlayerList = new List<BattlePawn>();
	public List<BattlePawn> enemyList = new List<BattlePawn>();
	public List<BattlePawn> enemyPoolList = new List<BattlePawn>();
	public List<BattlePawn> targetableEnemyList = new List<BattlePawn>();
	Queue<BattlePawn> battleOrderQueue = new Queue<BattlePawn>();
	List<BattlePawn> battleOrderList = new List<BattlePawn>();

	public int curWaveCount;
	//public bool isRageSkillCastable;
	public bool isFriendSummonPossible;
	public bool isCombatEnded;
	public bool isCombatWin;
	public bool isGameWin;
	public bool isGameOver;
	public int pawnId;
	public bool isBattleStarted;
	public float rageValue;
	public bool isRageSkillPrepared;
	//public bool isFriendSkillPrepared;
	public BattlePawn curActionPawn;
	public bool isSupportActionComplete;
	public bool isWaitingInput;
	[HideInInspector]
	public BattleCamera cam;
	bool bStartedIdleCamera;
	public BattleStatusCheck statusCheck;
	
	string					curBGName = "DefaultBG";
	Hashtable				bgHashtable = new Hashtable();					//	한번 생성된 배경은 재활용
	string					baseResDirectory = "Prefab/Battle/";
	
	//---------------------------------------------------------------
	//	결과 연출 관련
	//---------------------------------------------------------------		
	VictoryFieldSetting		victoryFieldLink = null;
	LoseFieldSetting		loseFieldLink = null;
	GameObject				defaultBGLink = null;
	public GameObject[]		VictoryActiveGoArray = null;
	//---------------------------------------------------------------
	//	End
	//---------------------------------------------------------------
		
	//---------------------------------------------------------------
	//	런타임 효과 관련
	//---------------------------------------------------------------	
	FogBank					fogBankLink = null;								//	런타임 포그 관리	
	public Material			effectHitMaterial;
	public float			effectHitTime = 0.1f;
	//---------------------------------------------------------------
	//	End
	//---------------------------------------------------------------  


	public bool isPvp;
	public int nTurn;
	int regionId;
	List<TurnSeq> turnSeqList = new List<TurnSeq>();
	[HideInInspector]
	public Transform playerPosParent;
	[HideInInspector]
	public Transform enemyPosParent;

	public GameObject cameraRoot;
	//public float timeScale = 1.0f;
	List<TakeInfo> cameraIdleTakes = new List<TakeInfo>();

	public bool bTestStartBattle = false;
	public int massBattleSideCount = 24;

	public float idleCamInterpolTime=4.0f;
	[HideInInspector]
	public float idleCamEnterTimeTmp;
	public bool bUseMassiveBattleUI;
	public int hpPlayerTotal;
	public int hpPlayerCur;
	public int hpEnemyTotal;
	public int hpEnemyCur;
	public MassiveBattle.UI massBattleUI;
	float leftTimeCur;

	[HideInInspector]
	public Quaternion realTimeLightLocalRotation;
	public bool bUseCamtakeSetting;
	[HideInInspector]
	public CamTakeSetting camtakeSet;
	[HideInInspector]
	public GameObject defauntBG;
	[HideInInspector]
	public Transform massUITrans;
	public GameObject [] BGChangeList;
	public int nBGSelected;
	public int numPlayerOfSide=4;
	[HideInInspector]
	public Transform uiRootTrans;
	[HideInInspector]
	public GameObject hpBarPrefab_player;
	[HideInInspector]
	public GameObject hpBarPrefab_enemy;
	public bool isPreventCamIdleTransition;

	public GameObject BGStaticObjectToChangeTrans;
	List<Vector3> BGStaticObjectPositionList = new List<Vector3>();
	List<Quaternion> BGStaticObjectRotationList = new List<Quaternion>();
	public Transform  BGStaticObjectTransformToChange;
	[HideInInspector]
	public Transform[] playerPos;
	[HideInInspector]
	public Transform[] enemyPos;

	public int nTotalWave=3;
	public Battle5vs5Config config;
	MemberModel[] memModelInLine;
	public int nEnemyFrontLine;
	public int nPlayerFrontLine;
	public int nRandomSeed;

	public bool Is5vs5New
	{
		get {
			if(numPlayerOfSide==5)
				return true;
			else
				return false;
		}
	}

	void Start()
	{
		if(BGStaticObjectToChangeTrans!=null) {
			BGStaticObjectPositionList.Add ( BGStaticObjectToChangeTrans.transform.position);
			BGStaticObjectRotationList.Add ( BGStaticObjectToChangeTrans.transform.rotation);
			if(BGStaticObjectTransformToChange!=null) {
				BGStaticObjectPositionList.Add ( BGStaticObjectTransformToChange.position);
				BGStaticObjectRotationList.Add ( BGStaticObjectTransformToChange.rotation);
			}
		}

		defauntBG = GameObject.Find("DefaultBG");



		if(Is5vs5New) {
			if(nRandomSeed==0)
				nRandomSeed = (int)DateTime.Now.Ticks;
			Debug.LogError("randomseed = "+nRandomSeed);
			UnityEngine.Random.seed = nRandomSeed;
			isPvp=false;
		}
		else {
			playerPosParent = GameObject.Find("PCPos").transform;
			enemyPosParent = GameObject.Find("NPCPos").transform;
			playerPos = new Transform[numPlayerOfSide];
			enemyPos = new Transform[numPlayerOfSide];
			for(int i=0; i<numPlayerOfSide; i++) {
				playerPos[i] = playerPosParent.FindChild((i+1).ToString());
				enemyPos[i] = enemyPosParent.FindChild((i+1).ToString());
			}
		}

		//if(cameraRoot==null)
		//	cameraRoot = GameObject.Find ("Camera");

		camtakeSet = CamTakeSetting.Instance;
		if(camtakeSet!=null)
			bUseCamtakeSetting=true;
		cameraRoot.AddComponent<CameraEventHandler>();
		/*
		if(bUseCamtakeSetting) {
			if(cameraRoot.GetComponent<LegionTouchCam>()==null) {
				LegionTouchCam ltc = cameraRoot.AddComponent<LegionTouchCam>();
				ltc.Reset();
			}
#if UNITY_EDITOR
			if(cameraRoot.GetComponent<LegionTouchCamKeys>()==null) {
				LegionTouchCamKeys k = cameraRoot.AddComponent<LegionTouchCamKeys>();
				k.Reset();
			}
			if(cameraRoot.GetComponent<LegionTouchCamMouse>()==null) {
				LegionTouchCamMouse m =cameraRoot.AddComponent<LegionTouchCamMouse>();
				m.Reset();
			}
#else
			EasyTouch et = FindObjectOfType<EasyTouch>();
			if(et==null) {
				GameObject easyTouchGo = new GameObject();
				easyTouchGo.name = "EasyTouch";
				easyTouchGo.AddComponent<EasyTouch>();
			}
			if(cameraRoot.GetComponent<CamTouchReceiver>()==null) {
				CamTouchReceiver recei = cameraRoot.AddComponent<CamTouchReceiver>();
				recei.Reset();
			}
#endif
		}*/
		if(Is5vs5New) {
		}
		else {
			massUITrans = BattleUIManager.Instance.battleUIObject.transform.FindChild("MassiveBattleUI");
			if(massUITrans!=null) {
				bUseMassiveBattleUI=true;
				massBattleUI = massUITrans.gameObject.GetComponent<MassiveBattle.UI>();
				//massUITrans.FindChild("top_middle").gameObject.SetActive(false);
	            //massUITrans.FindChild("buttons").gameObject.SetActive(false);
	            //massUITrans.FindChild("overdrive gauge").gameObject.SetActive(false);
				massUITrans.FindChild("overdrive charge").gameObject.SetActive(false);
				massBattleUI.NameEnemy = "";
	//			Debug.Log("Use massive battle ui");
			}
		}

		if(Is5vs5New)
			NetworkManager.Instance.C2S_LOGIN(AuthPlatformID.None, battleTestId, string.Empty, ResponseLogin, null);
		
		if(!bTestStartBattle)
			InitGame(UserData.Instance.isQuickPVPBattle);

		if(bUseMassiveBattleUI && UserData.Instance.userModel!=null)
			massBattleUI.NamePlayer = UserData.Instance.userModel.name;
	}

	private void ResponseLogin(ResponseModel<UserModel> result)
	{
		if (result.ecode != 0)
			return;

		Debug.Log(result.data.account);
		UserData.Instance.userModel = result.data;
		if(bUseMassiveBattleUI)
			massBattleUI.NamePlayer = UserData.Instance.userModel.name;
		InitGame(isPvp);
	}

	public void ShowTestBattleStartBtn(bool bShow)
	{
		if(Is5vs5New)
			return;
		GameObject.Find("UI Root").transform.FindChild("testpvestart").gameObject.SetActive(bShow);
		GameObject.Find("UI Root").transform.FindChild("testpvpstart").gameObject.SetActive(bShow);
		GameObject.Find("UI Root").transform.FindChild("testviewerstart").gameObject.SetActive(bShow);
	}

	void SelectRandomBG()
	{
		if(BGChangeList==null || BGChangeList.Length==0)
			return;
		for(int i=0; i<BGChangeList.Length; i++)
			BGChangeList[i].SetActive(false);
		nBGSelected = UnityEngine.Random.Range(0,BGChangeList.Length);
		Debug.Log ("nBGSelected="+nBGSelected);
		BGChangeList[nBGSelected].SetActive(true);
		BGChangeList[nBGSelected].transform.position = Vector3.zero;
	}

	void SelectBGStaticObjectTrans()
	{
		if(BGStaticObjectToChangeTrans == null)
			return;
		int nIndex = UnityEngine.Random.Range(0,BGStaticObjectPositionList.Count);
		BGStaticObjectToChangeTrans.transform.position = BGStaticObjectPositionList[nIndex];
		BGStaticObjectToChangeTrans.transform.rotation = BGStaticObjectRotationList[nIndex];
	}

	public void InitGame(bool _isPvp)
	{
		SelectRandomBG();
		if(bUseMassiveBattleUI && UserData.Instance.userModel!=null)
			massBattleUI.NamePlayer = UserData.Instance.userModel.name;
		if(bTestStartBattle) {
			ShowTestBattleStartBtn(false);
		}
		isPvp=_isPvp;

		isSupportActionComplete=false;
		isBattleStarted = true;
		pawnId=1;
		curWaveCount=0;
		isCombatEnded = false;
		isCombatWin=false;
		//isRageSkillCastable=false;
		isFriendSummonPossible=false;
		isGameOver = false;
		rageValue = UserData.Instance.rageValue;
		SetSuperGage();
		isRageSkillPrepared=false;
		//isFriendSkillPrepared=false;
		nTurn = -1;
		isWaitingInput=false;
	
		turnSeqList.Clear();
		InitManagers();
		InitCamera();
		//BattleResManager.Instance.LoadResources();
		InitMember();
		if(isPvp)
			MakePvpEnemy();
		else {
			MakeWaves();
			MakePveEnemy();
		}

		MakePlayerPawns();
		cam.Init();
		if(Is5vs5New)
			BattleUI.Instance.SetPlayerInfos();
		else
			BattleUIManager.Instance.SetPlayerInfos();

		//regionId = 100;
		//int[] memberNo = new int[membersIntoBattle.Count];
		//for(int i=0; i< membersIntoBattle.Count; i++)
		//	memberNo[i] = membersIntoBattle[i].no;
		//	Fog
		string strFogBankPath = this.baseResDirectory + "FogBank";
		GameObject goFogBankPrefab = Resources.Load( strFogBankPath ) as GameObject;
		if ( goFogBankPrefab != null )
		{
			GameObject goFog = GameObject.Instantiate( goFogBankPrefab ) as GameObject;
			this.fogBankLink = goFog.GetComponent( typeof( FogBank ) ) as FogBank;			
		}

		
		//if(bTestStartBattle)
		//{
			//테스트 임시로//
		if(bTestStartBattle)
			Well512.CreateStatic(randomSeedTest);
		else {
			Debug.Log("battleRandomSeed= "+UserData.Instance.battleRandomSeed);
			Well512.CreateStatic(UserData.Instance.battleRandomSeed);
		}
		
		StartCoroutine("CoBattleRoutine");

	}

	public void ClearGame()
	{
		foreach(BattlePawn pawn in enemyList)
		{
			pawn.pawnManifest.StopCurTake();
		}
		foreach(BattlePawn pawn in playerList)
		{
			pawn.pawnManifest.StopCurTake();
		}

		//ResourceManager.Inst.RetainChoiceMemberGo();
		//ResourceManager.Inst.ClearChoiceMemberComponents();
		ResourceManager.Inst.ClearAllChoiceModel();
	}

	public static void ClearBattlePawnComponent(GameObject go)
	{
		AudioSource [] audioS = go.GetComponents<AudioSource>();
		foreach( AudioSource _audio in audioS)
			Destroy(_audio);
		Destroy( go.GetComponent<PawnManifest>() );
		//Destroy( go.GetComponent<PawnEventHandler>() );
	}
	
//	private void ResponseQuickPvp(ResponseModel<UserModel> result)
//	{
//		Debug.Log("ResponseQuickPvp ecode="+result.ecode);
//		if (result.ecode != 0)
//			return;
//		Well512.Init(100);
//		StartCoroutine("CoBattleRoutine");
//	}
//
//	private void ResponseInvestigate(ResponseModel<ResearchStartModel> result)
//	{
//		Debug.Log("ResponseInvestigate ecode="+result.ecode+"  seed="+result.data.seed);
//		if (result.ecode != 0)
//			return;
//		Well512.Init(result.data.seed);
//		StartCoroutine("CoBattleRoutine");
//	}

	void InitManagers()
	{
		GameObject go = null;

		if(BattleSetting.Instance==null)
			go = Instantiate( Resources.Load ("Prefab/Battle/BattleSetting") as GameObject ) as GameObject;
		if(BattleCheat.Instance==null)
			go = Instantiate( Resources.Load ("Prefab/Battle/BattleCheat") as GameObject ) as GameObject;
		go = Instantiate( Resources.Load ("Prefab/Battle/BattleResManager") as GameObject ) as GameObject;
	}

	void InitCamera()
	{
		string takePath = "";
		int nMaxCamIdle = 7;

		takePath = "camera_idle0";
		for(int i=1; i<=nMaxCamIdle; i++) {
			TakeInfo tinfo = new TakeInfo();
			tinfo.take = Eventline.LoadTake(takePath+i.ToString() );
			//tinfo.length = tinfo.take.NumFrames/(float)tinfo.take.FrameRate;
			cameraIdleTakes.Add ( tinfo );
		}
	}

	public void StartIdleCamera()
	{
		//StartCoroutine("CoIdleCamera");
	}

	public IEventlinePlayer camTakePlayer = null;


	IEnumerator CoIdleCamera()
	{
		bStartedIdleCamera = true;
		UnityEngine.Object[] camActor = {(UnityEngine.Object)cameraRoot};

		while(true)
		{
			while(isPreventCamIdleTransition)
				yield return null;
			int nSelected = UnityEngine.Random.Range(0, cameraIdleTakes.Count);
			TakeInfo tinfo = cameraIdleTakes[nSelected];
			if(camTakePlayer!=null)
				camTakePlayer.Stop();
			camTakePlayer = Eventline.Play( tinfo.take, camActor,null, enter_time:idleCamEnterTimeTmp); 
			idleCamEnterTimeTmp=idleCamInterpolTime;

			//tinfo.length = tinfo.take.TakeLength/(float)tinfo.take.FrameRate;
			//Debug.Log(nSelected+"  camera idle  "+tinfo.length);
			//yield return new WaitForSeconds( tinfo.length );
		}
	}


	public void PauseIdleCamera(bool bPause)
	{
		return;// 포즈기능사용하지않음//

		if(bPause) {
			if(camTakePlayer!=null)
				camTakePlayer.Pause();
			isPreventCamIdleTransition = true;
		}
		else {
			isPreventCamIdleTransition = false;
			if(camTakePlayer!=null)
				camTakePlayer.Resume();
		}
	}

	Vector3 camPosReserve;
	Quaternion camRotReserve;
	public void SetSkillCamera(bool bOn)
	{ 
		if(bOn) {

			if(bUseCamtakeSetting)
				camtakeSet.SetSkillCamera(true);
			else
				TurnIdleCamera(false);
//			camPosReserve = cameraRoot.transform.position;
//			camRotReserve = cameraRoot.transform.rotation;
//			cameraRoot.transform.position = Vector3.zero;
//			cameraRoot.transform.rotation = Quaternion.identity;
		}
		else {
			//if(cameraRoot.transform.parent==null)// cameraidle 이벤트로 이미 호출된경우 두번 호출 방지//
			//	return;
			cameraRoot.transform.parent = null;
//			cameraRoot.transform.position = camPosReserve;
//			cameraRoot.transform.rotation = camRotReserve;
			if(bUseCamtakeSetting)
				camtakeSet.SetSkillCamera(false);
			else
				TurnIdleCamera(true);
		}
	}

	public void SetRageCamera(bool bOn)
	{
		if(bOn) {
			
			TurnIdleCamera(false);
			camPosReserve = cameraRoot.transform.position;
			camRotReserve = cameraRoot.transform.rotation;
			//cameraRoot.transform.position = Vector3.zero;
			//cameraRoot.transform.rotation = Quaternion.identity;
		}
		else {
			cameraRoot.transform.parent = null;
			cameraRoot.transform.position = camPosReserve;
			cameraRoot.transform.rotation = camRotReserve;
			TurnIdleCamera(true);
		}
	}


	public void TurnIdleCamera(bool bTurn)
	{
		if(bTurn && bStartedIdleCamera)
			return;

		if(camTakePlayer!=null)
			camTakePlayer.Stop ();
		camTakePlayer=null;
		bStartedIdleCamera = false;
		StopCoroutine("CoIdleCamera");

		if(bTurn) {
			StartCoroutine("CoIdleCamera");
		}
	}

	public void DetachCamera()
	{
		cameraRoot.transform.parent = null;
	}

	void InitMember()
	{
		if(Is5vs5New) {
			memModelInLine = new MemberModel[3];
			foreach(MemberModel memmodel in UserData.Instance.userModel.members) {
				if(memmodel.model==7)//templar
					memModelInLine[2] = memmodel;
				else if(memmodel.model==68)//assasin
					memModelInLine[1] = memmodel;
				else if(memmodel.model==19)//sorcerer
					memModelInLine[0] = memmodel;
			}
		}
		else {

			if(BattleCheat.Instance.cheatStartCharacter)
			{
				foreach(MemberModel memmodel in UserData.Instance.userModel.members) {
					Debug.LogError("cheat start character add  no="+memmodel.no);
					membersIntoBattle.Add( memmodel);
					if(membersIntoBattle.Count>=numPlayerOfSide)
						break;
				}
			}
			else {
				membersIntoBattle = UserData.Instance.userModel.m_ChoiceMemberList;
				while(membersIntoBattle.Count < numPlayerOfSide) {
					int nIndex = UnityEngine.Random.Range(0, UserData.Instance.userModel.m_ChoiceMemberList.Count);
					membersIntoBattle.Add ( UserData.Instance.userModel.m_ChoiceMemberList[nIndex] );
				}
			}
		}

		if(isPvp)
		{
			if(UserData.Instance.quickPVPUserModel!=null) {
				pvpMembersIntoBattle = UserData.Instance.quickPVPUserModel.m_ChoiceMemberList;
				while(pvpMembersIntoBattle.Count < numPlayerOfSide) {
					int nIndex = UnityEngine.Random.Range(0, UserData.Instance.quickPVPUserModel.m_ChoiceMemberList.Count);
					pvpMembersIntoBattle.Add ( UserData.Instance.quickPVPUserModel.m_ChoiceMemberList[nIndex] );
				}
			}
			else
				pvpMembersIntoBattle = membersIntoBattle;//temp
		}


	}

	void MakeWaves()
	{
		int areaID = 0;
		if(bTestStartBattle) {
			string loadedLvName = Application.loadedLevelName;
			Debug.Log("loadedLvName = "+loadedLvName);
			areaID = SceneController.GetAreaIDFromSceneName(loadedLvName);
		}
		else
			areaID = WorldSceneManager.GetSelectedAreaId();
		Debug.Log("wave make areaID="+areaID);

		//지역 조사일때..해당 지역에 나타나는 몬스터 확률 조사.///
		int totalWeight = 0;
		List<WaveNPCData> npcDataList = new List<WaveNPCData>();
		if(!WorldExtensionBattleStageScene.isExpansionWar && UserData.Instance.investigateNpcNo==null) {
			foreach(DRegionBattle rb in GameData.Inst.regionBattle)
			{
				if(areaID == rb.regionID) {
					totalWeight += rb.weight;
					WaveNPCData waveNpcData = new WaveNPCData();
					waveNpcData.npcID = rb.npcID;
					waveNpcData.prob = totalWeight;
					npcDataList.Add ( waveNpcData);

				}
			}
		}

		//3개의 웨이브 구성..  //
		for(int nWave=0; nWave<3; nWave++)
		{
			WaveData wData = new WaveData();
			wData.maxEnemy = numPlayerOfSide;
			wData.memModel = new MemberModel[wData.maxEnemy];
			for(int i=0; i<wData.maxEnemy; i++)
			{
				wData.memModel[i] = new MemberModel();
				if(WorldExtensionBattleStageScene.isExpansionWar)//확장전일때 wave데이타 적용//
				{
					if(nWave==0)
						SetNPCStat(wData.memModel[i], UserData.Instance.extendWarWave1[i]);
					else if(nWave==1)
						SetNPCStat(wData.memModel[i], UserData.Instance.extendWarWave2[i]);
					else if(nWave==2)
						SetNPCStat(wData.memModel[i], UserData.Instance.extendWarWave3[i]);
				}
				else {
					if(BattleCheat.Instance.cheatStartCharacter) {
						SetNPCStat(wData.memModel[i], BattleCheat.Instance.enemyStartId[i]);
					}
					else {
						if(UserData.Instance.investigateNpcNo==null) {
							//지역 조사일때 확률 계산.//
							int prob = UnityEngine.Random.Range(1, totalWeight+1);
							foreach(WaveNPCData wnd in npcDataList) {
								if(prob<= wnd.prob) {
									SetNPCStat(wData.memModel[i], wnd.npcID);
									break;
								}
							}

						}
						else {
							SetNPCStat(wData.memModel[i], UserData.Instance.investigateNpcNo[nWave][i]);
						}
					}
				}
			}

			waveDataList.Add(wData);
		}
		if(!Is5vs5New)
			PreCreateNPCCharacter();
	}

	bool IsModelUsedByNextWave(int modelID)
	{
		for(int nWave=curWaveCount; nWave<waveDataList.Count; nWave++) {
			for(int i=0; i<waveDataList[nWave].maxEnemy; i++) {
				if(waveDataList[nWave].memModel[i].model == modelID)
					return true;
			}
		}
		return false;
	}

	public bool HasModelInPool(int modelID)
	{
		for(int i=0; i<enemyPoolList.Count; i++)
		{
			if(enemyPoolList[i].memModelID == modelID && !enemyPoolList[i].bReserveUseForPool) {
				enemyPoolList[i].bReserveUseForPool = true;
				return true;
			}
		}
		return false;
	}

	void PreCreateNPCCharacter()
	{
		List<BattlePawn> tmpPawnList = new List<BattlePawn>();
		for(int nWave=0; nWave<waveDataList.Count; nWave++) {

			for(int k=0; k<enemyPoolList.Count; k++)
			{
				enemyPoolList[k].bReserveUseForPool=false;
			}
			tmpPawnList.Clear();
			for(int i=0; i<waveDataList[nWave].maxEnemy; i++) {
				if(!HasModelInPool(waveDataList[nWave].memModel[i].model)) {
					GameObject go = new GameObject();
					BattlePawn pawn = go.AddComponent<BattlePawn>();
					int pid = pawn.InitChar(i, waveDataList[nWave].memModel[i], false, true, 0);
					go.name = "enemy_"+pid.ToString();
					pawn.ClearMe();
					pawn.pawnGo.SetActive(false);
					pawn.gameObject.SetActive(false);
					tmpPawnList.Add ( pawn);
					Debug.Log ("Precreate pawn  modelid="+waveDataList[nWave].memModel[i].model);
				}
			}
			foreach(BattlePawn tmpPawn in tmpPawnList)
				enemyPoolList.Add( tmpPawn);
		}
	}



	void SetNPCStat(MemberModel memModel, int npcID)
	{
		DNpcData npcData = GameData.Inst.GetNPCData(npcID );
		if(npcData==null) {
			Debug.LogError("npc data null  for npcId "+npcID);
			return;
		}
		memModel.m_StatWithItem.maxHp = npcData.HP;
		memModel.m_StatWithItem.level = npcData.lv;
		memModel.m_StatWithItem.def = npcData.armor;
		memModel.m_StatWithItem.resist = npcData.res;
		memModel.m_StatWithItem.prior = npcData.init;
		memModel.m_StatWithItem.atkType = npcData.atkType;
		memModel.m_StatWithItem.atk = npcData.atkRating;
		memModel.m_StatWithItem.critical = npcData.skillProb;
		memModel.m_StatWithItem.taunt = npcData.taunt;
		memModel.model = npcData.modelID; //npc 모델 아이디//
		
		memModel.traits = new short[5];
		memModel.traits[0] = npcData.trait1;
		memModel.traits[1] = npcData.trait2;
		memModel.traits[2] = npcData.trait3;
		memModel.traits[3] = npcData.trait4;
		memModel.traits[4] = npcData.trait5;

//		Debug.Log("SetNPCStat  npcID="+npcID+"   npcModelId="+npcData.modelID);
	}

	public void UpdateTotalHP(bool _isPlayer, int _mNo, int _amount, bool isHeal)
	{
		if(bUseMassiveBattleUI) {
			if(_isPlayer) {
				hpPlayerCur += _amount;
				hpPlayerCur = Mathf.Clamp( hpPlayerCur, 0, hpPlayerTotal);
				float ratio = Mathf.Clamp( (float)hpPlayerCur/(float)hpPlayerTotal, 0, 1);
				Debug.Log("player hp ratio  "+ratio);
				massBattleUI.SetHp(MassiveBattle.ESide.PLAYER,ratio, 3.0f);
				if(isHeal) {
					//BattleUIManager.Instance.ShowhealHUDText(_isPlayer, _mNo, _amount);
				}
				else {
					massBattleUI.ShowHpDecreaseEffect(MassiveBattle.ESide.PLAYER);
					//BattleUIManager.Instance.ShowDamageHUDText(_isPlayer, _mNo, -_amount);
				}
			}
			else {
				hpEnemyCur += _amount;
				hpEnemyCur = Mathf.Clamp( hpEnemyCur, 0, hpEnemyTotal);
				float ratio = Mathf.Clamp( (float)hpEnemyCur/(float)hpEnemyTotal, 0, 1);
				Debug.Log("enemy hp ratio  "+ratio);
				massBattleUI.SetHp(MassiveBattle.ESide.ENEMY,ratio, 3.0f);
				if(isHeal) {
					//BattleUIManager.Instance.ShowhealHUDText(_isPlayer, _mNo, _amount);
				}
				else {
					massBattleUI.ShowHpDecreaseEffect(MassiveBattle.ESide.ENEMY);
					//BattleUIManager.Instance.ShowDamageHUDText(_isPlayer, _mNo, -_amount);
				}
			}
		}
	}

	public void UpdateEnemyHP()
	{
		if(bUseMassiveBattleUI) {
			float ratio = Mathf.Clamp( (float)hpEnemyCur/(float)hpEnemyTotal, 0, 1);
			Debug.Log("UpdateEnemyHP enemy hp ratio  "+ratio);
			massBattleUI.SetHp(MassiveBattle.ESide.ENEMY,ratio, 0.0f);
		}
	}
	
	void MakePlayerPawns()
	{
		hpPlayerTotal=0;

		if(Is5vs5New) {
			nPlayerFrontLine = 0;
			int [] lineRandom = new int[5];
			if(config.playerLineArrange!=null && config.playerLineArrange.Length>0) {
				int nCount=0;
				for(int k=0; k<config.playerLineArrange[0]; k++) {
					lineRandom[nCount++] = 2;
				}
				for(int k=0; k<config.playerLineArrange[1]; k++) {
					lineRandom[nCount++] = 1;
				}
				for(int k=0; k<config.playerLineArrange[2]; k++) {
					lineRandom[nCount++] = 0;
				}
			}
			else {
				for(int i=0; i<5; i++)
					lineRandom[i] = UnityEngine.Random.Range(0,3);
			}
			for(int i=0; i<5; i++) {
				if(lineRandom[i]>nPlayerFrontLine)
					nPlayerFrontLine = lineRandom[i];
			}

			for(int i=0; i<5; i++)
			{
				GameObject go = BattlePawn.CreatePawnGo(lineRandom[i]);
				BattlePawn pawn = go.AddComponent<BattlePawn>();
				pawn.pawnGo = go;
				MemberModel memModel = memModelInLine[lineRandom[i]];
				int pid = pawn.InitChar5vs5(i, memModel, false, false, lineRandom[i]);
				pawn.lightProbeAnchorForSkill = defauntBG.transform.FindChild("LightProbeAnchor_Skill_"+(i+1).ToString());
				//go.name = "player_"+(i+1).ToString();
				playerList.Add(pawn);
				targetablePlayerList.Add(pawn);
				hpPlayerTotal += pawn.hp;
			}
		}
		else {
			int nCount = membersIntoBattle.Count;
			for(int i=0; i<nCount; i++)
			{
				GameObject go = new GameObject();
				BattlePawn pawn = go.AddComponent<BattlePawn>();
				MemberModel memModel = null;

				memModel = membersIntoBattle[i];
				int pid = pawn.InitChar(i, memModel, false, false, 0);
				pawn.lightProbeAnchorForSkill = defauntBG.transform.FindChild("LightProbeAnchor_Skill_"+(i+1).ToString());
				go.name = "player_"+(i+1).ToString();
				playerList.Add(pawn);
				targetablePlayerList.Add(pawn);
				hpPlayerTotal += pawn.hp;
				//if(i==0 && bUseMassiveBattleUI)
				//	massBattleUI.SetPortraitPlayer( pawn.myModel );
			}
		}

		hpPlayerCur=hpPlayerTotal;
		if(bUseMassiveBattleUI) {
			if(!BattleCheat.Instance.playerHPBarName.IsNullOrEmpty() )
				massBattleUI.NamePlayer = BattleCheat.Instance.playerHPBarName;
			massBattleUI.SetHp(MassiveBattle.ESide.PLAYER, 1.0f, 0f);
			leftTimeCur = 180.0f;
			massBattleUI.LeftTimeCur = leftTimeCur;
		}
	}

	void MakePvpEnemy()
	{
		int nCount = pvpMembersIntoBattle.Count;

		hpEnemyTotal=0;
		for(int i=0; i<nCount; i++)
		{
			GameObject go = new GameObject();
			BattlePawn pawn = go.AddComponent<BattlePawn>();
			MemberModel memModel = null;

			memModel = pvpMembersIntoBattle[i];
			int pid = pawn.InitChar(i, memModel, true, false, 0);
			go.name = "pvp_enemy_"+(i+1).ToString();
			enemyList.Add(pawn);
			targetableEnemyList.Add(pawn);
			hpEnemyTotal += pawn.hp;
			//if(i==0 && bUseMassiveBattleUI)
			//	massBattleUI.SetPortraitEnemy( pawn.myModel );
		}
		hpEnemyCur=hpEnemyTotal;
		if(bUseMassiveBattleUI) {
			if(BattleCheat.Instance.enemyHPBarName.Length>0)
				massBattleUI.NameEnemy = BattleCheat.Instance.enemyHPBarName[0];
			massBattleUI.SetHp(MassiveBattle.ESide.ENEMY, 1.0f, 0f);
			if( UserData.Instance.quickPVPUserModel != null )
				massBattleUI.NameEnemy = UserData.Instance.quickPVPUserModel.name;
		}
		if(Is5vs5New)
			BattleUI.Instance.ResetEnermyHpBar();
		else
			BattleUIManager.Instance.ResetEnermyHpBar();
	}

	void MakePveEnemy() 
	{
		hpEnemyTotal=0;

		if(Is5vs5New) {
			nEnemyFrontLine = 5;
			int [] lineRandom = new int[5];
			if(config.enemyLineArrange!=null && config.enemyLineArrange.Length>0) {
				int nCount=0;
				for(int k=0; k<config.enemyLineArrange[0]; k++) {
					lineRandom[nCount++] = 3;
				}
				for(int k=0; k<config.enemyLineArrange[1]; k++) {
					lineRandom[nCount++] = 4;
				}
				for(int k=0; k<config.enemyLineArrange[2]; k++) {
					lineRandom[nCount++] = 5;
				}
			}
			else {
				for(int i=0; i<5; i++)
					lineRandom[i] = UnityEngine.Random.Range(3,6);
			}
			for(int i=0; i<5; i++) {
				if(lineRandom[i]<nEnemyFrontLine)
					nEnemyFrontLine = lineRandom[i];
			}

			for(int i=0; i<5; i++)
			{
				GameObject go = BattlePawn.CreatePawnGo(lineRandom[i]);
				BattlePawn pawn = go.AddComponent<BattlePawn>();
				pawn.pawnGo = go;
				MemberModel memModel = memModelInLine[5-lineRandom[i]];
				int pid = pawn.InitChar5vs5(i, memModel, false, true, lineRandom[i]);
				//go.name = "enemy_"+pid.ToString();
				enemyList.Add(pawn);
				targetableEnemyList.Add(pawn);
				hpEnemyTotal += pawn.hp;

			}
		}
		else {
			for(int i=0; i<waveDataList[curWaveCount].maxEnemy; i++)
			{
				GameObject go = null;
				BattlePawn pawn = null;
				MemberModel memModel = waveDataList[curWaveCount].memModel[i];
				BattlePawn poolPawn = FindInEnemyPool(memModel.model); // 이전 웨이브에서 재활용가능한것 체크//
				if(!BattleCheat.Instance.cheatModel && !BattleCheat.Instance.cheatStartCharacter && poolPawn != null) {
					go = poolPawn.gameObject;
					pawn = poolPawn;
				}
				else {
					go = new GameObject();
					pawn = go.AddComponent<BattlePawn>();
				}
				int pid = pawn.InitChar(i, memModel, false, true, 0);
				go.name = "enemy_"+pid.ToString();
				enemyList.Add(pawn);
				targetableEnemyList.Add(pawn);
				hpEnemyTotal += pawn.hp;

				if(bUseMassiveBattleUI) {
					if(BattleCheat.Instance.enemyHPBarName.Length>curWaveCount)
						massBattleUI.NameEnemy = BattleCheat.Instance.enemyHPBarName[curWaveCount];
				}
			}
		}
		hpEnemyCur=hpEnemyTotal;
		if(bUseMassiveBattleUI)
			massBattleUI.SetHp(MassiveBattle.ESide.ENEMY, 1.0f, 0f);
		if(Is5vs5New)
			BattleUI.Instance.ResetEnermyHpBar();
		else
			BattleUIManager.Instance.ResetEnermyHpBar();
	}

	void PrepareNextWave()
	{
		foreach(BattlePawn pawn in enemyList)
		{
			pawn.ClearMe();
			pawn.pawnGo.SetActive(false);
			//ClearBattlePawnComponent(pawn.pawnGo);

			if(!Is5vs5New) {
				// 모델이 다음 웨이브에서 사용될것인지 조사하여 파괴할지 결정.//
				if(IsModelUsedByNextWave(pawn.memModelID) ) {
					pawn.gameObject.SetActive(false);
					enemyPoolList.Add ( pawn);
					Debug.Log(pawn.memModelID+"  AddToEnemyPool  "+pawn.name+"  poolcount="+enemyPoolList.Count);
				}
				else{
				//	pawn.DestroyMe();
				}
				//Destroy(pawn.gameObject);
			}
		}
		enemyList.Clear();
		targetableEnemyList.Clear();
		battleOrderQueue.Clear();
		foreach(BattlePawn pawn in playerList)
			pawn.InitCombat();
		MakePveEnemy();
		//Invoke ("ClearEnemyPool", 1.0f);
		SelectRandomBG();
		SelectBGStaticObjectTrans();
		if(Is5vs5New)
			BattleUI.Instance.SetPlayerInfos();
		else
			BattleUIManager.Instance.SetPlayerInfos();
	}

//	void ClearEnemyPool()
//	{
//		foreach(BattlePawn pawn in  enemyPoolList)
//		{
//			Debug.LogError("ClearEnemyPool  "+pawn.name);
//			Destroy(pawn.pawnGo);
//			Destroy(pawn.gameObject);
//		}
//		enemyPoolList.Clear ();
//	}

	public BattlePawn FindInEnemyPool(int modelID)
	{
		int nFoundPawn = -1;
		BattlePawn foundPawn = null;
		for(int i=0; i<enemyPoolList.Count; i++)
		{
			if(enemyPoolList[i].memModelID == modelID) {
				nFoundPawn = i;
				break;
			}
		}
		if(nFoundPawn==-1)
			Debug.LogError("cannot find In EnemyPool  "+modelID);
		else {
			foundPawn = enemyPoolList[nFoundPawn];
			foundPawn.gameObject.SetActive(true);
			enemyPoolList.RemoveAt(nFoundPawn);
			Debug.Log(modelID+"  FindInEnemyPool  "+foundPawn.name+"  poolcount="+enemyPoolList.Count);
		}
		return foundPawn;
	}

	public void CharacterEnterStage()
	{
		foreach(BattlePawn pawn in enemyList) {
			if(!pawn.isDead)
				pawn.pawnManifest.EnterStage(false);
		}

		foreach(BattlePawn pawn in playerList) {
			if(!pawn.isDead)
				pawn.pawnManifest.EnterStage(false);
		}
	
		/*else {
			//등장 패밀리 구동//
			Object [] actors = new Object[playerList.Count+1];
			int i=0;
			foreach(BattlePawn pawn in playerList)
			{
				pawn.pawnManifest.gameObject.SetActive(true);
				pawn.pawnManifest.EnterStageMove();
				pawn.pawnManifest.curTakeName = "idle01";// 패밀리로 구동하면 takename이 셋팅이 안되므로 강제 세팅//
				pawn.pawnManifest.eCurTake = ETake.idle01;
				actors[i] = (Object)pawn.pawnManifest.gameObject;
				i++;
			}
			actors[i] = (Object)cameraRoot;
			TakeInfo tinfo = new TakeInfo();
			tinfo.take = Eventline.LoadTake("common/battle_enterstage01");
			tinfo.length = tinfo.take.NumFrames/(float)tinfo.take.FrameRate;
			maxEnterStageLength = tinfo.length;
			Eventline.Play( tinfo.take, actors, null );
		}*/
	}

	float EnemyEnterStage()
	{
		foreach(BattlePawn pawn in enemyList)
			pawn.pawnManifest.EnterStage(false);
		return 0;
	}

	void DetermineAttackOrder()
	{
		battleOrderList.Clear();
		//공격 순서 결정//
		BattleFormula.CalcAttackOrder(playerList, enemyList);
		if(BattleCheat.Instance.randomAttackOrder) {
			List<BattlePawn> allPawnList = new List<BattlePawn>();
			foreach(BattlePawn pawn in playerList) {
				if(pawn.CanDoAction())
					allPawnList.Add( pawn);
			}
			foreach(BattlePawn pawn in enemyList) {
				if(pawn.CanDoAction())
					allPawnList.Add( pawn);
			}
			while(allPawnList.Count>0)
			{
				int nIndex = UnityEngine.Random.Range(0, allPawnList.Count);
				BattlePawn pawn = allPawnList[nIndex];
				pawn.isAtkOrderDetermined=true;
				battleOrderList.Add(pawn);
				allPawnList.RemoveAt(nIndex);
			}
		}
		else {
			while(true)
			{
				float maxPrior = -1;
				BattlePawn maxPriorPawn = null;
				foreach(BattlePawn pawn in playerList) {
					if(pawn.CanDoAction() && !pawn.isAtkOrderDetermined && pawn.IsAtkOrderFirst(maxPrior)) {
						maxPrior = pawn.atkOrder;
						maxPriorPawn = pawn;
					}
				}

				foreach(BattlePawn pawn in enemyList) {
					if(pawn.CanDoAction() && !pawn.isAtkOrderDetermined && pawn.IsAtkOrderFirst(maxPrior)) {
						maxPrior = pawn.atkOrder;
						maxPriorPawn = pawn;
					}
				}

				if(maxPrior==-1 || maxPriorPawn==null)
					break;
				maxPriorPawn.isAtkOrderDetermined=true;
				battleOrderList.Add(maxPriorPawn);
				//Debug.Log("battleOrderQueue enqueue  pid="+maxPriorPawn.pid);
			}
		}
	}

	public void ShowWaveUI()
	{
		if(Is5vs5New)
			return;
		if(bUseCamtakeSetting) {
			if(curWaveCount==0)
				BattleUIManager.Instance.ShowStarBattleAnimation();
			else
				BattleUIManager.Instance.SetWaveText(curWaveCount+1, waveDataList.Count);
		}
	}

	int battleResult;
	int[] seqNo = null;
	int[] seqType = null;
	IEnumerator CoBattleRoutine()
	{
		if(bUseCamtakeSetting) {
			cam.ShowWaveCam(curWaveCount, isPvp);
		}
		else
			StartIdleCamera();

		CharacterEnterStage();
		bool isAllEnterStageComplete=false;
		while(!isAllEnterStageComplete) {
			isAllEnterStageComplete=true;
			foreach(BattlePawn pawn in playerList) {
				if(!pawn.pawnManifest.bEnterStageComplete) {
					isAllEnterStageComplete=false;
					break;
				}
			}

			foreach(BattlePawn pawn in enemyList) {
				if(!pawn.pawnManifest.bEnterStageComplete) {
					isAllEnterStageComplete=false;
					break;
				}
			}
			yield return null;
		}
	

		if(bUseCamtakeSetting) {
			camtakeSet.allowTouchCam=true;
		}
		else {
			if(!Is5vs5New)
				BattleUIManager.Instance.ShowStarBattleAnimation();
			yield return new WaitForSeconds(0.1f);
		}

		while(BattleCheat.Instance.turnDoesntStart)
			yield return null;

		if(Is5vs5New) {
			int nWaveCount=0;
			while(!isGameOver)
			{
				bool isReadyToNextEnemy=true;
				foreach(BattlePawn pawn in playerList) {
					if(!pawn.UpdateAction())
						isReadyToNextEnemy=false;
				}
				foreach(BattlePawn pawn in enemyList)
					pawn.UpdateAction();

				if(targetablePlayerList.Count==0) {
					isGameOver=true;
					break;
				}

				if(isReadyToNextEnemy) {
					nWaveCount++;
					if(nWaveCount==nTotalWave)
						isGameOver=true;
					else {
						yield return new WaitForSeconds(0.5f);
						foreach(BattlePawn pawn in playerList)
							pawn.MoveForNextEnemy();
						
						bool isMoveDone=false;
						while(!isMoveDone) {
							isMoveDone=true;
							foreach(BattlePawn pawn in playerList) {
								if(!pawn.pawnManifest.bDoneMoveForNextEnemy) {
									isMoveDone=false;
									break;
								}
							}
							yield return null;
						}

						Battle5vs5Center.Instance.ClearAllOccupy();

						PrepareNextWave();

						nPlayerFrontLine=0;
						foreach(BattlePawn pawn in playerList) {
							if(!pawn.isDead) {
								pawn.InitVars();
								pawn.myCurLine = pawn.myInitialLine;
								if(pawn.myInitialLine>nPlayerFrontLine)
									nPlayerFrontLine=pawn.myInitialLine;
							}
						}
						foreach(BattlePawn pawn in playerList) {
							if(!pawn.isDead) {
								pawn.SetInitialPosition();
								pawn.pawnManifest.originalPos = pawn.startPosition;
								pawn.SetBackPosition();
								pawn.pawnGo.SetActive(false);
								pawn.pawnManifest.StopCurTake();
								pawn.pawnManifest.StopEventLineTween();
							}
						}
						CharacterEnterStage();
						isAllEnterStageComplete=false;
						while(!isAllEnterStageComplete) {
							isAllEnterStageComplete=true;
							foreach(BattlePawn pawn in playerList) {
								if(!pawn.isDead && !pawn.pawnManifest.bEnterStageComplete) {
									isAllEnterStageComplete=false;
									break;
								}
							}
							
							foreach(BattlePawn pawn in enemyList) {
								if(!pawn.pawnManifest.bEnterStageComplete) {
									isAllEnterStageComplete=false;
									break;
								}
							}
							yield return null;
						}
					}
				}
				yield return null;
			}
		}
		else {
			while(!isGameOver)
			{
				DetermineAttackOrder();
				battleOrderQueue.Clear();		
				foreach(BattlePawn pawn in battleOrderList)
					battleOrderQueue.Enqueue(pawn);

				EBattleStatus battleStatus = EBattleStatus.NextTurn;
				while(battleOrderQueue.Count>0)
				{
					BattlePawn pawn = battleOrderQueue.Dequeue();
					Debug.Log("========== turn  "+pawn.pawnManifest.name+"     queue="+battleOrderQueue.Count);
					if( BattleCheat.Instance.CheckInfiniteTurnAttacker(pawn) )
						continue;

					//필살기 시전이 다음 턴에 바로 되도록 하기위해//
					if(isRageSkillPrepared && !pawn.isUltimateReady)
						continue;


					//오버드라이브 모드일때//
					if(BattleManager.Instance.bOverdriveMode) {
						while(!IsAllPawnIdle()) {
							statusCheck.SetRoutineWaitStatus(EBattleWaitStatus.OverDriveAllPawnIdle, pawn);
							yield return null;
						}
						statusCheck.ClearRoutineWaitStatus();
						BattleUIManager.Instance.ShowOverDriveStartTextEffect();

						yield return new WaitForSeconds(2f);

						StartOverdriveMode();

						while(bOverdriveMode)// 전투 로직 홀드//
						{
							statusCheck.SetRoutineWaitStatus(EBattleWaitStatus.OverDrive, pawn);
							yield return null;
						}
						statusCheck.ClearRoutineWaitStatus();
						yield return new WaitForSeconds(1.0f);//끝나고 정리될 시간 필요. 너무 바로 진행되면 damage가 attack 플레이를 씹어버리는 경우가 있다.//
					}


					if(!pawn.CanDoAction()) {
						Debug.Log(" Can not do action ... skip   "+pawn.pawnManifest.name);
						continue;
					}


					//턴 진행이 빨라서...적 전멸후 내턴이 바로 2번 들어올경우 발생할수 있으므로 기다린다..//

					while(!pawn.isDead && !pawn.pawnManifest.IsIdlePlaying() ) {
						statusCheck.SetRoutineWaitStatus(EBattleWaitStatus.IdleWaiting, pawn);
						yield return null;
					}
					statusCheck.ClearRoutineWaitStatus();

					// 빠른 턴 적용으로 인해 적 전멸 체크를 여기서도 해주자..//
					battleStatus = CheckCombatResult();
					if(battleStatus != EBattleStatus.NextTurn)
						break;

					pawn.DoAction();



					while(!pawn.IsActionComplete() ) {
						statusCheck.SetRoutineWaitStatus(EBattleWaitStatus.ActionComplete, pawn);
						yield return null;
					}
					statusCheck.ClearRoutineWaitStatus();

					battleStatus = CheckCombatResult();
					if(battleStatus != EBattleStatus.NextTurn)
						break;
				}

				battleOrderQueue.Clear();

				if(battleStatus == EBattleStatus.NextWave)
				{
					yield return new WaitForSeconds(2.0f);
					PrepareNextWave();
					if(bUseCamtakeSetting)
						cam.ShowWaveCam(curWaveCount, false);
					else
						BattleUIManager.Instance.SetWaveText(curWaveCount+1, waveDataList.Count);
					EnemyEnterStage();
					isAllEnterStageComplete=false;
					while(!isAllEnterStageComplete) {
						isAllEnterStageComplete=true;
						foreach(BattlePawn pawn in enemyList) {
							if(!pawn.pawnManifest.bEnterStageComplete) {
								isAllEnterStageComplete=false;
								break;
							}
						}
						yield return null;
					}
				}

				yield return null;
			}
		}
		if(!Is5vs5New)
			BattleEndRoutine();
	}

	public void BattleEndRoutine()
	{
		StartCoroutine("CoBattleEnd");
	}

	IEnumerator CoBattleEnd()
	{
		cam.ClearCamAtkFocus();
		BattleUIManager.Instance.isClickedSpeedButton=false;
		Time.timeScale = 1.0f;
		
		yield return new WaitForSeconds(2.0f);

		Debug.Log("*** Battle Ended");
		foreach(BattlePawn pawn in playerList) {
			pawn.pawnManifest.StopCurTake();
			pawn.ClearHpBar();
		}
		foreach(BattlePawn pawn in enemyList) {
			pawn.pawnManifest.StopCurTake();
			pawn.ClearHpBar();
		}
		if(isGameWin) {
			battleResult=1;
			Debug.Log("-- result Win!");
			this.StartCoroutine( this.ChangeToVictory() );
			
		}
		else {
			battleResult=2;		
			Debug.Log("-- result Lose");
			this.StartCoroutine( this.ChangeToLose() );
		}
		
		if(turnSeqList.Count>0) {
			seqNo = new int[turnSeqList.Count];
			seqType = new int[turnSeqList.Count];
		}
		for(int i=0; i<turnSeqList.Count; i++) {
			seqNo[i] = turnSeqList[i].turn;
			seqType[i] = turnSeqList[i].type;
			Debug.Log( string.Format("turnSeqList  turn={0}  type={1}",seqNo[i], seqType[i]) );
		}
		
		NetworkManager.Instance.C2S_LEGION_GET(ResponseGetLegionInfo);
		
		yield return new WaitForSeconds(5.0f);
		
		if(isPvp)
		{	
			if ( this.fogBankLink != null )
				this.fogBankLink.ChangeToDefault ();
		}

	}

	private void ResponseGetLegionInfo(ResponseModel<UserModel> result)
	{
		if( result.ecode != 0 )
		{
			Popup_OneButton po = PopupManager.PushPopup(PopupKind.OneButton) as Popup_OneButton;
			po.SetPopupWithTitleAndBody(TextController.GetStringWithId("uiCommonTextwarning"), TextController.GetStringWithId(string.Format("systemErrorText{0}", Mathf.Abs(result.ecode))));
			return;
		}

		UserData.Instance.userModel = result.data;

		if( !isPvp && UserData.Instance.counterAttackMsgId == 0)
		{
			if( !WorldExtensionBattleStageScene.isExpansionWar )
			{
				NetworkManager.Instance.C2S_SEND_TO_RESEARCH_RESULT(ResponseResearchResult, WorldSceneManager.GetSelectedAreaId(), battleResult, seqNo, seqType);
			}
			else
			{
				NetworkManager.Instance.C2S_SEND_TO_EXPANSION_RESULT(ResponseExpansionResult, WorldSceneManager.GetSelectedAreaId(), UserData.Instance.userModel.regions.expansionWarStep==0?1:(int)UserData.Instance.userModel.regions.expansionWarStep, battleResult);
			}
		}
		else if( UserData.Instance.isQuickPVPBattle || UserData.Instance.counterAttackMsgId != 0 )
		{
			NetworkManager.Instance.C2S_QUICK_END(battleResult, ResponseQuickPvpResult);
		}

	}

	private void ResponseQuickPvpResult(ResponseModel<PvpEndResult> result)
	{
		Debug.LogError("ResponseQuickPvpResult error="+result.ecode);
		UserData.Instance.quickPvPResultData = result.data;
	}

	private void ResponseResearchResult(ResponseModel<ResearchResultModel> result)
	{
		if (result.ecode != 0)
			return;
		
		Debug.Log("ResponseBattleResult ecode="+result.ecode);

		UserData.Instance.researchResultData = result.data;
		if( isGameWin )
		{
			UserData.Instance.userModel.exp += result.data.legionExp;
			UserData.Instance.userModel.regions.regionMap_Dic[WorldSceneManager.GetSelectedAreaId().ToString()].regionExp += result.data.regionExp;
			UserData.Instance.userModel.kina += result.data.kina;
			for(int i=0; i<result.data.memberExp.Length; i++)
			{
				UserData.Instance.userModel.members_dic[result.data.memberExp[i][0].ToString()].exp += result.data.memberExp[i][1];
			}
			WorldSceneManager.isSuccessSearch = true;
		}

		if ( this.fogBankLink != null )		
			this.fogBankLink.ChangeToDefault ();
		
//		SceneController.LoadLevel("Main");
	}

	private void ResponseExpansionResult(ResponseModel<ExpansionWarResultModel> result)
	{
		UserData.Instance.expansionWarResultData = result.data;
		if ( this.fogBankLink != null )		
			this.fogBankLink.ChangeToDefault ();
		
//		SceneController.LoadLevel("Main");
	}

	private void ResponseEndRaidBossBattle(ResponseModel<RaidBossEndModel> result)
	{
		UserData.Instance.raidBossResultData = result.data;
	}

	public void AddTurnSeq(int seqType)
	{
		//seqType : 1 rage skill
		//          2 friend skill
		turnSeqList.Add ( new TurnSeq(nTurn, seqType) );
	}

	public EBattleStatus CheckCombatResult()
	{
		bool isPlayerAllDead = true;
		foreach(BattlePawn pawn in playerList)
		{
			if(!pawn.isDead) {
				isPlayerAllDead=false;
				break;
			}
		}
		bool _isTimeOver=false;
		if(bUseMassiveBattleUI && leftTimeCur==0)
			_isTimeOver=true;
		if(BattleCheat.Instance.timeOverDontEnd)
			_isTimeOver=false;
		if(isPlayerAllDead || BattleCheat.Instance.gameLose ||  _isTimeOver )
		{
			isGameOver=true;
			isGameWin=false;
			return EBattleStatus.EndBattle;
		}
		bool isEnemyAllDead = true;
		foreach(BattlePawn pawn in enemyList)
		{
			if(!pawn.isDead) {
				isEnemyAllDead=false;
				break;
			}
		}
		if(isEnemyAllDead || BattleCheat.Instance.gameWin || BattleCheat.Instance.forceNextWave)
		{
			BattleCheat.Instance.forceNextWave=false;
			if(BattleCheat.Instance.gameWin || isPvp || curWaveCount==waveDataList.Count-1)
			{
				isGameOver=true;
				isGameWin=true;
				return EBattleStatus.EndBattle;
			}
			else
			{
				curWaveCount++;
				Debug.Log( string.Format("***** Wave {0}*****", curWaveCount+1) );
				return EBattleStatus.NextWave;
			}
		}
		return EBattleStatus.NextTurn;
	}



	void HiddenForResult()
	{
		BattleUIManager.Instance.HideBattleUI ();
		Camera.main.gameObject.SetActive ( false );

		/*
		if ( this.defaultBGLink == null )
			this.defaultBGLink = GameObject.Find ( "DefaultBG" );
		this.defaultBGLink.SetActive ( false );
		*/

		//	적들은 모두 안그림
		for ( int i = 0; i < this.enemyList.Count; ++i )
		{
			BattlePawn b_pawn = this.enemyList[ i ];
			if ( b_pawn == null )
				continue;
			b_pawn.pawnManifest.gameObject.SetActive ( false );
		}
	}
	

	public IEnumerator ChangeToVictory()
	{

		float rDelayTime = BattleUIManager.Instance.ShowBattleResultTextEffect();
		yield return new WaitForSeconds( rDelayTime );

		SoundController.PlayBGM("BGM_Battle_Win", false);

		this.HiddenForResult();		
        /*
		//if(this.fogBankLink!=null)
		//	this.fogBankLink.ChangeToVictory();				
		if( this.VictoryActiveGoArray != null )
		{
			for( int i = 0;		i < this.VictoryActiveGoArray.Length;		++i )			
				this.VictoryActiveGoArray[ i ].SetActive( true );			
		}

		//string strVictoryPrefabPath = this.baseResDirectory + "VictoryField";
		string strVictoryPrefabPath = this.baseResDirectory + "VictoryField_v2";
		GameObject victoryPrefab = Resources.Load( strVictoryPrefabPath ) as GameObject;
		if( victoryPrefab != null )
		{
			GameObject goVictoryField = GameObject.Instantiate( victoryPrefab ) as GameObject;		
			this.victoryFieldLink = goVictoryField.GetComponent( typeof( VictoryFieldSetting ) ) as VictoryFieldSetting;
			if ( this.victoryFieldLink != null )
			{
				this.victoryFieldLink.gameObject.SetActive ( true );
				float rMaxAniTime = this.victoryFieldLink.PlaceCharacter( ref this.playerList );
				//yield return new WaitForSeconds ( rMaxAniTime );
								
				SS_ShadowManager.Instance.UpdateCameraEvents( this.victoryFieldLink.CameraLink );


				this.victoryFieldLink.PlayCameraAni();
				yield return new WaitForSeconds( rMaxAniTime );
								
				this.victoryFieldLink.PlayFadeIn ();
				yield return new WaitForSeconds ( 0.1f );

				this.victoryFieldLink.RunScreenFX( true );				

				for ( int i = 0; i < this.playerList.Count; ++i )
				{
					BattlePawn b_pawn = this.playerList[ i ];
					if ( b_pawn == null )
						continue;
					b_pawn.pawnManifest.StopCurTake ();
				}
				this.victoryFieldLink.PlayFadeOut ();					
			}
		}
        */
        for (int i = 0; i < this.playerList.Count; ++i)
        {
            BattlePawn b_pawn = this.playerList[i];
            if (b_pawn == null)
                continue;
            b_pawn.pawnManifest.gameObject.GetComponent<Animation>().Play("lobby01");
        }
		BattleUIManager.Instance.ShowBattleResult();

		if( this.VictoryActiveGoArray != null )
		{
			for( int i = 0; i < this.VictoryActiveGoArray.Length; ++i ) {
				if(this.VictoryActiveGoArray[ i ]!=null)
					this.VictoryActiveGoArray[ i ].SetActive( false );
			}
		}
	}

	public IEnumerator ChangeToLose()
	{
		//if ( this.fogBankLink != null )		
		//	this.fogBankLink.ChangeToDefeat ();

		float rDelayTime = BattleUIManager.Instance.ShowBattleResultTextEffect();
		yield return new WaitForSeconds( rDelayTime );

		SoundController.PlayBGM("BGM_Battle_Lose", false);
		
		this.HiddenForResult();	

        //string strLosePrefabPath = this.baseResDirectory + "LoseField_v2";
        //GameObject losePrefab = Resources.Load( strLosePrefabPath ) as GameObject;
        //if( losePrefab != null )
        //{
        //    GameObject goLoseField = GameObject.Instantiate( losePrefab ) as GameObject;
        //    this.loseFieldLink = goLoseField.GetComponent ( typeof ( LoseFieldSetting ) ) as LoseFieldSetting;
        //    if ( this.loseFieldLink != null )
        //    {
        //        this.loseFieldLink.gameObject.SetActive ( true );
        //        float rMaxAniTime = this.loseFieldLink.PlaceCharacter ( ref this.playerList );
        //        SS_ShadowManager.Instance.UpdateCameraEvents( this.loseFieldLink.CameraLink );
        //        this.loseFieldLink.PlayCameraAni();
        //        yield return new WaitForSeconds ( rMaxAniTime );				

        //        this.loseFieldLink.PlayFadeIn ();
        //        yield return new WaitForSeconds ( 0.1f );

        //        this.loseFieldLink.RunScreenFX( true );				
				
        //        for ( int i = 0; i < this.playerList.Count; ++i )
        //        {
        //            BattlePawn b_pawn = this.playerList[ i ];
        //            if ( b_pawn == null )
        //                continue;
        //            b_pawn.pawnManifest.StopCurTake ();
        //        }
        //        this.loseFieldLink.PlayFadeOut ();
        //    }
        //}
        for (int i = 0; i < this.playerList.Count; ++i)
        {
            BattlePawn b_pawn = this.playerList[i];
            if (b_pawn == null)
                continue;
            b_pawn.pawnManifest.gameObject.GetComponent<Animation>().Play("lobby01");
        }
		BattleUIManager.Instance.ShowBattleResult ();
	}
	public void ChangeToBattle()
	{ 
		if( this.fogBankLink != null )
		{
			this.fogBankLink.ChangeToDefault();
		}
		if ( this.victoryFieldLink != null )
		{
			this.victoryFieldLink.gameObject.SetActive ( false );
		}

		this.defaultBGLink.SetActive( true );		
	}


	public void ChangeBackground( string strName )
	{
		if( this.fogBankLink != null )
		{
			if( strName.CompareTo( "DefaultBG" ) == 0 )
			{
				this.fogBankLink.ChangeToDefault();
			}
			else
			{
				this.fogBankLink.ChangeToSpecialAttack();
			}
		}
		if( this.defaultBGLink == null )
		{
			this.defaultBGLink = GameObject.Find( "DefaultBG" );	
			if( this.defaultBGLink == null )
				return;
		}

		if( strName.CompareTo( this.curBGName ) == 0 )
			return;

		
		GameObject goFind = null;
		if( strName.CompareTo( "DefaultBG" ) == 0 )
		{			
			this.defaultBGLink.SetActive( true );
			if( bgHashtable.Contains( this.curBGName ) == true )
			{
				goFind = bgHashtable[ this.curBGName ] as GameObject;
				goFind.SetActive( false );				
			}
		}
		else
		{		
			if( bgHashtable.Contains( strName ) == true )
			{
				goFind = bgHashtable[ strName ] as GameObject;				
			}
			else
			{
				//string strSpecialBGPath = this.baseResDirectory + "Cutscene_Bg_01";
				string strSpecialBGPath = this.baseResDirectory + strName;
				GameObject goSpecialPrefab = Resources.Load ( strSpecialBGPath ) as GameObject;
				if ( goSpecialPrefab == null )
				{
					return;
				}

				goFind = GameObject.Instantiate ( goSpecialPrefab ) as GameObject;
				goFind.transform.position = Vector3.zero;
				goFind.transform.rotation = Quaternion.identity;
				bgHashtable.Add( strName, goFind );				
			}
			goFind.SetActive ( true );
			this.defaultBGLink.SetActive( false );
		}
		curBGName = strName;
	}


	IEnumerator DelayAction( float delayTime )
	{
		yield return new WaitForSeconds (delayTime);
	}

	public void RevivePlayer(int playerNo)
	{
		foreach(BattlePawn pawn in playerList)
		{
			if(pawn.mNo == playerNo)
				pawn.Revive();
		}
	}

	public void ReviveEnemyPlayer(int playerNo)
	{
		foreach(BattlePawn pawn in enemyList)
		{
			if(pawn.mNo == playerNo)
				pawn.Revive();
		}
	}

	public void PrepareRageSkill()
	{
		Debug.LogError("PrepareRageSkill "+curActionPawn);
		if(battleOrderList.Count==0)
			return;
		//isRageSkillCastable=false;
		isRageSkillPrepared=true;
		int nCurActionPawnIndex=0;
		for(int i=0; i< battleOrderList.Count; i++)
		{
			if(curActionPawn == battleOrderList[i]) {
				nCurActionPawnIndex=i;
				break;
			}
		}
		if(curActionPawn==null)
			nCurActionPawnIndex=-1;

		///// 필살기를 쓸 다음 턴 아군에게 이펙트 표시//
		bool bFoundNextAlly = false;
		for(int i=nCurActionPawnIndex+1; i< battleOrderList.Count; i++)
		{
			// 다음 차례 아군 캐릭터//
			if(battleOrderList[i].isPlayer && battleOrderList[i].CanDoAction() ) {
				bFoundNextAlly=true;
				battleOrderList[i].SetUltimateReady();
				break;
			}
		}
		if(!bFoundNextAlly)
		{
			for(int i=0; i<nCurActionPawnIndex; i++)
			{
				// 다음 차례 아군 캐릭터//
				if(battleOrderList[i].isPlayer && battleOrderList[i].CanDoAction() ) {
					bFoundNextAlly=true;
					battleOrderList[i].SetUltimateReady();
					break;
				}
			}
		}
		// 다음 아군이 없으면 나자신에게로..//
		if(!bFoundNextAlly) {
			if(curActionPawn.isPlayer && curActionPawn.CanDoAction())
				curActionPawn.SetUltimateReady();
		}

		if(rageValue>=50) {
			rageValue -= 50;
			UserData.Instance.rageValue -= 50;
			SetSuperGage();
		}
	}

	void Update()
	{
//		Time.timeScale = timeScale;
		if(isBattleStarted && bUseMassiveBattleUI) {
			leftTimeCur -= Time.deltaTime;
			if(leftTimeCur<0)
				leftTimeCur=0;

			massBattleUI.LeftTimeCur = leftTimeCur;
		}

		if(BattleSetting.Instance.old_showPlayerHpBar != BattleSetting.Instance.showPlayerHpBar) {
			BattleSetting.Instance.old_showPlayerHpBar = BattleSetting.Instance.showPlayerHpBar;
			foreach(BattlePawn pawn in playerList)
				pawn.hpBar.gameObject.SetActive(BattleSetting.Instance.showPlayerHpBar);
		}

		if(BattleSetting.Instance.old_showEnemyHpBar != BattleSetting.Instance.showEnemyHpBar) {
			BattleSetting.Instance.old_showEnemyHpBar = BattleSetting.Instance.showEnemyHpBar;
			foreach(BattlePawn pawn in targetableEnemyList)
				pawn.hpBar.gameObject.SetActive(BattleSetting.Instance.showEnemyHpBar);
		}
	}
}
